/**
 * 歌曲搜索 歌词获取 切歌 歌曲列表
 */
const service = require('./');
const Utils = require('../utils');
const crypto = require('crypto');
const bigInt = require('big-integer');
const modulus = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7';
const nonce = '0CoJUm6Qyw8W8jud';
const pubKey = '010001';

class Music {

  getSecretKey() {
    return Utils.Random.randomWord(
      16,
      'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
    );
  }

  aesEncrypt(str, key) {
    key = Buffer.from(key, "binary");
    const lv = Buffer.from('0102030405060708', "binary");
    const cipher = crypto.createCipheriv('AES-128-CBC', key, lv);
    let encrypted = cipher.update(str, 'utf8', 'base64');
    encrypted += cipher.final('base64');
    return encrypted;
  }

  rsaEncrypt(text, pubKey, modulus) {
    const _text = text.split('').reverse().join('');
    const biText = bigInt(Buffer.from(_text).toString('hex'), 16),
      biEx = bigInt(pubKey, 16),
      biMod = bigInt(modulus, 16),
      biRet = biText.modPow(biEx, biMod);
    return biRet.toString(16).padStart(256, '0');
  }

  encrypt(data) {
    const str = JSON.stringify(data),
      secKey = this.getSecretKey(),
      encText = this.aesEncrypt(
        this.aesEncrypt(str, nonce),
        secKey
      ),
      encSecKey = this.rsaEncrypt(secKey, pubKey, modulus);
    return {
      params: encText,
      encSecKey
    };
  }

  async requestWeb(url, data, method = 'get', cookie = '') {
    const result = await service.httpclient.http(
      `http://music.163.com${url}`, {
        method: method.toUpperCase(),
        headers: {
          'Accept': '*/*',
          'Accept-Language': 'zh-CN,zh;q=0.8,gl;q=0.6,zh-TW;q=0.4',
          'Connection': 'keep-alive',
          'Content-Type': 'application/x-www-form-urlencoded',
          'Referer': 'http://music.163.com',
          'Host': 'music.163.com',
          'Cookie': cookie,
          'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/602.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/602.1'
        },
        data: this.encrypt(data),
        dataType: 'json'
      }
    );
    if (result.res.statusCode !== 200 || !result.data) {
      return this.request(url, data, method, cookie);
    }
    return result.data;
  }

  async request(url, data = null, method = 'get') {
    const result = await service.httpclient.http(
      `http://music.163.com${url}`, {
        method: method.toUpperCase(),
        headers: {
          'Referer': 'http://music.163.com',
          'Cookie': 'appver=1.5.6',
          'Content-Type': 'application/x-www-form-urlencoded',
        },
        data,
        dataType: 'json'
      }
    );
    return result.data;
  }

  async searchSong(songName) {
    const result = await this.requestWeb(
      '/weapi/cloudsearch/get/web', {
        s: songName,
        offset: 0,
        limit: 1,
        type: 1
      },
      'post'
    );
    if (result.code === 200 && result.result.songs.length) {
      const song = result.result.songs[0];
      return {
        id: song.id,
        name: song.name,
        songerName: song.ar[0].name,
        album: song.al.name,
        thumb: song.al.picUrl,
        duration: Number.parseInt(song.dt / 1000), // 时长
      };
    }
    return null;
  }

  async getSongLyric(songId) {
    const result = await this.request(
      `/api/song/lyric?os=osx&id=${songId}&lv=-1&kv=-1&tv=-1`
    );
    if (result.code === 200 && !result.nolyric) {
      return result.lrc.lyric;
    }
    return '';
  }

  async getSong(songId) {
    const result = await service.httpclient.get({
      url: `https://api.imjad.cn/cloudmusic/?type=song&id=${songId}`
    });
    if (result.code === 200) {
      return {
        url: result.data[0].url,
        expi: result.data[0].expi,
      };
    }
    return null;
  }

}


module.exports = new Music();